<?php

// +----------------------------------------------------------------------
// | EasyAdmin
// +----------------------------------------------------------------------
// | PHP交流群: 763822524
// +----------------------------------------------------------------------
// | 开源协议  https://mit-license.org 
// +----------------------------------------------------------------------
// | github开源项目：https://github.com/zhongshaofa/EasyAdmin
// +----------------------------------------------------------------------


namespace app\common\controller;

use WechatPay\GuzzleMiddleware\WechatPayMiddleware;
use WechatPay\GuzzleMiddleware\Util\PemUtil;
use WechatPay\GuzzleMiddleware\Util\AesUtil;
use WechatPay\GuzzleMiddleware\Validator;
use think\facade\Db;
use app\BaseController;
use EasyAdmin\tool\CommonTool;
use think\facade\Env;
use think\Model;

/**
 * Class AdminController
 * @package app\common\controller
 */
class AdminController extends BaseController
{

    use \app\common\traits\JumpTrait;

    /**
     * 当前模型
     * @Model
     * @var object
     */
    protected $model;

    /**
     * 字段排序
     * @var array
     */
    protected $sort = [
        'id' => 'desc',
    ];

    /**
     * 允许修改的字段
     * @var array
     */
    protected $allowModifyFields = [
        'status',
        'sort',
        'remark',
        'is_delete',
        'is_auth',
        'title',
    ];

    /**
     * 不导出的字段信息
     * @var array
     */
    protected $noExportFields = ['delete_time', 'update_time'];

    /**
     * 下拉选择条件
     * @var array
     */
    protected $selectWhere = [];

    /**
     * 是否关联查询
     * @var bool
     */
    protected $relationSearch = false;

    /**
     * 模板布局, false取消
     * @var string|bool
     */
    protected $layout = 'layout/default';


    /**
     * 初始化方法
     */
    protected function initialize()
    {
        parent::initialize();
        $this->layout && $this->app->view->engine()->layout($this->layout);
    }

    /**
     * 模板变量赋值
     * @param string|array $name 模板变量
     * @param mixed $value 变量值
     * @return mixed
     */
    public function assign($name, $value = null)
    {
        return $this->app->view->assign($name, $value);
    }

    /**
     * 解析和获取模板内容 用于输出
     * @param string $template
     * @param array $vars
     * @return mixed
     */
    public function fetch($template = '', $vars = [])
    {
        return $this->app->view->fetch($template, $vars);
    }

    /**
     * 重写验证规则
     * @param array $data
     * @param array|string $validate
     * @param array $message
     * @param bool $batch
     * @return array|bool|string|true
     */
    public function validate(array $data, $validate, array $message = [], bool $batch = false)
    {
        try {
            parent::validate($data, $validate, $message, $batch);
        } catch (\Exception $e) {
            $this->error($e->getMessage());
        }
        return true;
    }

    /**
     * 构建请求参数
     * @param array $excludeFields 忽略构建搜索的字段
     * @return array
     */
    protected function buildTableParames($excludeFields = [],$filed_arr = [])
    {
        $get = $this->request->get('', null, null);
        $page = isset($get['page']) && !empty($get['page']) ? $get['page'] : 1;
        $limit = isset($get['limit']) && !empty($get['limit']) ? $get['limit'] : 15;
        $filters = isset($get['filter']) && !empty($get['filter']) ? $get['filter'] : '{}';
        $ops = isset($get['op']) && !empty($get['op']) ? $get['op'] : '{}';
        // json转数组
        $filters = json_decode($filters, true);
        $ops = json_decode($ops, true);
        $where = [];
        $excludes = [];

        // 判断是否关联查询
        $tableName = CommonTool::humpToLine(lcfirst($this->model->getName()));

        foreach ($filters as $key => $val) {
            if (in_array($key, $excludeFields)) {
                $excludes[$key] = $val;
                continue;
            }
            $op = isset($ops[$key]) && !empty($ops[$key]) ? $ops[$key] : '%*%';
            if ($this->relationSearch && count(explode('.', $key)) == 1) {
                $key = "{$tableName}.{$key}";
            }
            if(isset($filed_arr[$key])){
                $key = $filed_arr[$key];
            }
            switch (strtolower($op)) {
                case '=':
                    $where[] = [$key, '=', $val];
                    break;
                case '%*%':
                    $where[] = [$key, 'LIKE', "%{$val}%"];
                    break;
                case '*%':
                    $where[] = [$key, 'LIKE', "{$val}%"];
                    break;
                case '%*':
                    $where[] = [$key, 'LIKE', "%{$val}"];
                    break;
                case 'range':
                    [$beginTime, $endTime] = explode(' - ', urldecode($val));
                    $where[] = [$key, '>=', strtotime($beginTime)];
                    $where[] = [$key, '<=', strtotime($endTime)];
                    break;
                case 'rangeint':
                    [$min, $max] = explode(' - ', $val);
                    $where[] = [$key, '>=', $min];
                    $where[] = [$key, '<=', $max];
                    break;
                default:
                    $where[] = [$key, $op, "%{$val}"];
            }
        }
        return [$page, $limit, $where, $excludes];
    }

    /**
     * 下拉选择列表
     * @return \think\response\Json
     */
    public function selectList()
    {
        $fields = input('selectFields');
        $data = $this->model
            ->where($this->selectWhere)
            ->field($fields)
            ->select();
        $this->success(null, $data);
    }
    
    // 更新证书
    public function updateCertificates(){
        $merchantId = sysconfig('wxapp','mchid');
        $merchantSerialNumber = sysconfig('wxapp','serial_num');
        $merchantPrivateKey = PemUtil::loadPrivateKey('cert/apiclient_key.pem');
        $wechatpayMiddleware = WechatPayMiddleware::builder()
        ->withMerchant($merchantId, $merchantSerialNumber, $merchantPrivateKey)
        ->withValidator(new NoopValidator) // NOTE: 设置一个空的应答签名验证器，**不要**用在业务请求
        ->build();
        $stack = \GuzzleHttp\HandlerStack::create();
        $stack->push($wechatpayMiddleware, 'wechatpay');
        $client = new \GuzzleHttp\Client(['handler' => $stack]);
        $resp = $client->request('GET', 'https://api.mch.weixin.qq.com/v3/certificates', [ // 注意替换为实际URL
            'headers' => [ 'Accept' => 'application/json' ]
        ]);
        $encrypt_certificate = json_decode($resp->getBody(),true)['data'][0]['encrypt_certificate'];
        $serial_no = json_decode($resp->getBody(),true)['data'][0]['serial_no'];
        $aesUtil = new AesUtil(sysconfig('wxapp','signkey'));
        $res = $aesUtil->decryptToString($encrypt_certificate['associated_data'],$encrypt_certificate['nonce'],$encrypt_certificate['ciphertext']);
        file_put_contents('cert/cert.pem',$res);
        Db::name('system_config')->where([['name','=','serial_no']])->update(['value'=>$serial_no]);
        //echo $serial_no;
    }
    public function getWxacode($page, $env_version = 'release'){
        $access_token = $this->getAccessToken();
        $url = 'https://api.weixin.qq.com/wxa/getwxacode?access_token='.$access_token;
        $json = $this->http_request($url,json_encode(['path'=>$page, 'env_version'=>$env_version]));
        $res = json_decode($json, true);
        if(!empty($res['errcode'])){
            $this->success('二维码生成失败'.$res['errmsg']);
        }
        $path = 'upload/qrcode';
        $file = date('Ymd') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
        if(!file_exists($path)){
            mkdir($path,0755);
        }
        $filename = $path.'/'.$file.'.png';
        file_put_contents($filename,$json);
        return $filename;
    }
    public function getWxacodeUnlimit($page, $scene = '', $env_version = 'release'){
        $access_token = $this->getAccessToken();
        $url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token='.$access_token;
        $json = $this->http_request($url,json_encode(['page'=>$page, 'env_version'=>$env_version, 'scene'=>$scene, 'check_path'=>false,]));
        $res = json_decode($json, true);
        if(!empty($res['errcode'])){
            $this->error('二维码生成失败'.$res['errmsg']);
        }
        $path = 'upload/qrcode';
        $file = date('Ymd') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
        if(!file_exists($path)){
            mkdir($path,0755);
        }
        $filename = $path.'/'.$file.'.png';
        file_put_contents($filename,$json);
        return $filename;
    }
}
class NoopValidator implements Validator
{
    public function validate(\Psr\Http\Message\ResponseInterface $response)
    {
        return true;
    }
}